home *** CD-ROM | disk | FTP | other *** search
- .TITLE DEHEX
- .SBTTL Stuart Hecht and Eric McQueen, Stevens Inst of Technology
-
- .LIBRARY /SYS$LIBRARY:STARLET/
- .LIBRARY /SYS$LIBRARY:LIB/
- .IDENT /1.1.02/
- ;++
- ;1.1.01
- ;Updated March 9, 1898, by Susan Webb and Jerry Holliday of Lockheed Aircraft
- ;Systems Co, Marietta, GA, to work for files longer than 64K. Added lines
- ;marked with ";JH".
- ;--
- ;++
- ;1.1.02
- ;Updated March 15, 1989, by Tom Allebrandi of Advanced Computer Consulting,
- ;Inc, Charlottesville, VA. (ta2@acci.com)
- ;
- ;On March 14, 1989, I pulled this file and VMSMIT.HEX from Columbia via
- ;KERMSRV. After compiling, this utility would not decode the VMSMIT file.
- ;The problem was the 1.1.01 fix noted above.
- ;
- ;I have removed the 1.1.01 fix and coded it so that it works correctly.
- ;My changes are marked ";ta2"
- ;--
-
- ;++
- ;This will take a set hexidecimal strings created by the hexify program and
- ; recreate the source file(s).
- ;--
-
- .EXTRN LIB$GET_INPUT
- .EXTRN LIB$PUT_OUTPUT
- .EXTRN DSC$K_DTYPE_T
- .EXTRN DSC$K_CLASS_S
- .EXTRN SS$_NORMAL
- .MCALL $FAB ; RMS calls
- .MCALL $RAB
- .MCALL $CLOSE
- .MCALL $CONNECT
- .MCALL $CREATE
- .MCALL $DISCONNECT
- .MCALL $GET
- .MCALL $OPEN
- .MCALL $WRITE
- .MCALL $RAB_STORE
- .MCALL $FAB_STORE
-
- .SBTTL Definitions of symbols
-
- DWRLUN =1 ; Disk read LUN
- DWWLUN =5 ; Disk write LUN
- TRUE =1 ; True
- FALSE =0 ; False
- KNORMAL =0 ; No error
- LEFTBYTE=^O377*^O400 ; All ones in left byte
- HEXOFFSET=7 ; Offset to get to 'A from '9+1
- CR =13. ; Carriage return
- LF =10. ; Line feed
- MAX.MSG =256. ; Maximum number of chars from XK
- RCV.SOH =^A/:/ ; Receive start of packet
- RCV.EOL =13. ; End of line character
- MSB =128. ; Most significant bit
- ; Packet types currently supported
- PKDATA =00 ; Data packet code
- PKRFM =255. ; Record format
- PKRAT =254. ; Record attributes
- PKMRS =253. ; Maximum record size
- PKALQ =252. ; File length(blocks)
- PKFILNM =251. ; File name
- PKEOF =250. ; End of task file
- ;
-
-
- .SBTTL RMS Data
-
- .PSECT $PLIT$,LONG
-
- DEFALT: .ASCIZ 'SYS$DISK:' ; System default.
- DEFALN =.-DEFALT ; Size of the default device.
- .EVEN
-
- .SBTTL Data
-
-
- M$FILE: .BYTE CR,LF
- .ASCII 'Please type the file name: '
- L$FILE= .-M$FILE
-
- M$CRLF: .BYTE CR,LF ; Data for carriage return/line feed
- L$CRLF =.-M$CRLF
-
- ;M$AK:
- ; .ASCII 'Y' ; Data for aknowledged
-
- M$NAK:
- ;.ASCII 'N' ; Data for not aknowledged
- .ASCII 'BAD CHECK SUM' ; Data for not aknowledged
- L$NAK =.-M$NAK
-
- M$UN:
- ;.ASCII 'U' ; Data for unrecognized code
- .ASCII 'UNKNOWN BLOCK TYPE' ; Data for unrecognized code
- L$UN =.-M$UN
-
- M$RMS: .BYTE CR,LF,LF
- .ASCII 'RMS ERROR'
- L$RMS =.-M$RMS
-
- M$REC: .BYTE CR,LF,LF
- .ASCII 'RECEIVE ERROR - Try again.'
- L$REC =.-M$REC
- .EVEN
-
-
- .SBTTL Storage locations
-
- .PSECT $OWN$,LONG
- .ALIGN LONG
-
- MSGDSC: .BLKW 1 ; Data block for terminal output
- .BYTE DSC$K_DTYPE_T
- .BYTE DSC$K_CLASS_S
- ADDR: .ADDRESS ADDR
- LNGADR: .BLKL 1
-
- INP_STR_D: ; Key string desciptor
- .BLKL 1
- INP_BUF: .ADDRESS ADDR
-
- INP_STR_LEN: .BLKL 1 ; Key string length
-
- WTCOUNT: .BLKL 1 ; Number of characters written
- LENGTH: .BLKL 1 ; Length of data portion of packet
- OPENFL: .BLKL 1 ; Tells us if the file is open
-
- CHKSUM: .BLKL 1 ; Checksum for the line
- ADDRESS: .BLKL 1 ; Current address
- ALQLOC: .BLKW 2 ; Storage for allocation
-
- OUT.N: .BLKB 28. ; Space for output file name
- OUT.L =.-OUT.N ; Length of output file name
-
- INP.N: .BLKB 28. ; Space for input file name
- INP.L =.-INP.N ; Length of input file name
-
- .EVEN ; Need to start RDBUF on even boundary
- RDBUF: .BLKB MAX.MSG ; XK read buffer
- .EVEN
- WTBUF: .BLKB 512. ; Disk write buffer
- .EVEN
-
-
-
- .SBTTL RMS Data structures
- .ALIGN LONG
-
- RDFAB:: $FAB DNA=DEFALT,DNS=DEFALN,FNA=INP.N,FNS=INP.L,-
- LCH=DWRLUN,FAC=GET,SHR=GET
-
- .ALIGN LONG
- RDRAB:: $RAB FAB=RDFAB,RAC=SEQ ; Beginning of RAB block.
-
- .ALIGN LONG
- WTFAB:: $FAB DNA=DEFALT,DNS=DEFALN,FNA=OUT.N,FNS=OUT.L,-
- LCH=DWWLUN,FAC=PUT,SHR=NIL
-
- WTRAB:: $RAB FAB=WTFAB,RAC=SEQ ; Beginning of RAB block.
-
-
- .SBTTL Start of program
-
- .PSECT $CODE$,LONG,EXE
-
- DEHEX:: .WORD ^M<>
- FILE: MOVAB M$FILE,R11 ; Output the get file name message
- MOVZBL #L$FILE,R12
- MOVAB INP.N,R10 ; Get the file name
- MOVZBL #INP.L,R1
- JSB READ
- TSTL R0 ; Check for no input
- BEQL FILE ; Go back and get some
- ;Open the file
- MOVAL RDFAB,R1 ; Put address of FAB into R1.
- $FAB_STORE FAB=R1,FNS=R0 ; Tell RMS file name length
- $OPEN #RDFAB ; Open the file
- JSB RMSERR ; Check for file error
- MOVAL RDRAB,R1 ; Put address of RAB into R1.
- ; Put address of user buffer and size and record buffer and size in RAB.
- $RAB_STORE RAB=R1,UBF=RDBUF,RBF=RDBUF,USZ=#MAX.MSG,RSZ=#MAX.MSG
- $CONNECT #RDRAB ; Connect to record.
- JSB RMSERR ; Check for file error
-
-
- .SBTTL Do the real work
- ;++
- ; Do the actual work
- ;--
- BEGIN: MOVAL M$CRLF,R10 ; Get a return/linefeed and output them
- MOVZBL #L$CRLF,R1
- JSB WRITE
-
- 20$: CLRL WTCOUNT ; Initialize the pointer
- CLRL ADDRESS ; Initialize the address
- CLRL OPENFL ; Set the file to not open
-
- .SBTTL Main loop
-
- ; Main loop to get data
- DOLIN:
- CLRL CHKSUM ; Clear the checksum
- JSB RECEIVE ; Get the line
- JSB CVTBIN ; Convert it to a real number
- MOVL R10,LENGTH ; Save the length
- NAB: JSB CVTBIN ;
- BISL R10,R3 ; Save a byte of the address
- ASHL #8.,R3,R3 ; Make room for next byte
- SOBGEQ LNGADR,NAB ; If there are more than 2 bytes
- JSB CVTBIN ;
- BISL R10,R3 ; Fill in the low byte of address
-
- ;ta2 The fix for 1.1.01 converted two more hex values here. As of March
- ; 1989, this doesn't appear to be required. The conversion has been
- ; removed.
-
- JSB CVTBIN ;ta2 Pick up the record type code
-
- CMPL #PKDATA,R10 ; Check to see if this is regular data
- BNEQ NOTDAT ; If not then check the special cases
- ; Check for end of hex file
- TSTL R3 ; Check to see if the address is all
- BNEQ DATST ; zero, if not then branch
- TSTL LENGTH ; Check to see if the length is zero
- BNEQ DATST ; also, if not then branch
- JMP FINISH ; Must be end of hex file so finish up
- ; Regular data to put into the file
- DATST: TSTL OPENFL ; Check to see if the file is open yet
- BNEQ DAT1 ; If it is then skip the open
- JSB OPEN ; Open the file
- DAT1: CMPL R3,ADDRESS ; Check for null compression
- BEQL 10$ ; If none compressed then continue past
- CLRL R10 ; Make a null
- JSB PUT ; and put it into the file
- INCL ADDRESS ; Point to next address
- BRW DAT1 ; Go see if there are any more nulls
- ; Go to work on the HEX we got on the line
- 10$: MOVL LENGTH,R2 ; Get the length
- TSTL R2 ; See if there is any data
- BEQL 30$ ; If not then branch
- 25$: JSB CVTBIN ; Convert it
- JSB PUT ; Put the character in the file
- INCL ADDRESS ; Increment the address
- SOBGTR R2,25$ ; Repeat until all done
- 30$: BRW LINDON ; Go finish this line
-
-
-
- NOTDAT: MOVAL WTFAB,R5 ; Get the FAB address
- CMPL #PKRFM,R10 ; Check to see if this is record fmt
- BNEQ NOTRFM ; If not then don't do this stuff
- ; Store the Record format (FIX, VAR, ...)
- JSB CVTBIN ;
- $FAB_STORE FAB=R5,RFM=R10 ; Store the record format
- BRW LINDON ; Go finish this line
-
- NOTRFM: CMPL #PKRAT,R10 ; Check to see if this is record type
- BNEQ NOTRAT ; If not then branch
- ; Store the record type (CR, ...)
- JSB CVTBIN ;
- $FAB_STORE FAB=R5,RAT=R10 ; Store the record type
- BRW LINDON ; Go finish this line
-
- NOTRAT: CMPL #PKMRS,R10 ; Check to see if this is max record
- BNEQ NOTMRS ; size, branch if not
- ; Get the maximum record size (512. for tasks)
- JSB CVTBIN ; Convert high order byte
- MOVL R10,R3 ; Save it
- ASHL #8.,R3,R3 ; Shift it to the high order byte
- JSB CVTBIN ; Convert low order byte
- BISL R10,R3 ; Put low order word into R3 also
- $FAB_STORE FAB=R5,MRS=R3 ; Store the maximum record size
- BRW LINDON ; Go finish this line
-
- NOTMRS: CMPL #PKALQ,R10 ; Check to see if this is allocation
- BNEQ NOTALQ ; If not then branch
- ; Get the file length (in blocks)
- JSB CVTBIN ; Convert high order byte
- MOVL R10,R3 ; Save it
- ASHL #8.,R3,R3 ; Shift it to the high order byte
- JSB CVTBIN ; Convert low order byte
- BISL R10,R3 ; Put low order word into R3 also
- MOVZWL R3,ALQLOC ; Save it
- $FAB_STORE FAB=R5,ALQ=ALQLOC ; Store the allocation
- BRW LINDON ; Go finish this line
-
- NOTALQ: CMPL #PKFILNM,R10 ; Check to see if this is file name
- BNEQ NOTFILNM ; If not then branch
- ; Get the file name
- MOVL LENGTH,R2 ; Get the length
- $FAB_STORE FAB=R5,FNS=R2 ; Store the file name length
- MOVAB OUT.N,R3 ; Get the output file name address
- 25$: JSB CVTBIN ; Convert next character of the name
- MOVB R10,(R3)+ ; Save the character
- SOBGTR R2,25$ ; Repeat until all done
- MOVAB M$CRLF,R10 ;
- MOVZBL #L$CRLF,R1 ;
- JSB WRITE ; Output a return/line feed
- MOVAB OUT.N,R10 ;
- MOVL LENGTH,R1 ;
- JSB WRITE ; Output the file name
- MOVAB M$CRLF,R10 ;
- MOVZBL #L$CRLF,R1 ;
- JSB WRITE ; Output a return/line feed
- BRW LINDON ; Go finish this line
-
-
-
- NOTFILNM:
- CMPL #PKEOF,R10 ; Check to see if this is end of task
- BNEQ NOTPKEOF ; If not then branch
- ; End of ouput file record found
- JSB CLTSK ; Close the task file
- CLRL WTCOUNT ; Initialize the pointer
- CLRL ADDRESS ; Initialize the address
- JMP LINDON ; Go finish this line
-
- ; Unknown code
- NOTPKEOF: ; Since we don't know what the code
- MOVAB M$UN,R10 ; just send the unknown code text to
- MOVZBL #L$UN,R1 ; the terminal
- JSB WRITE ;
- JMP DOLIN ; Go do next input line
-
-
- .SBTTL Finished with this line
-
- ; Line processed without a problem
- LINDON:
- ; MOVAB M$AK,R10 ; Get the data address of the
- ; single character
- ; MOVZBL #1,R1 ; Only write single char to terminal
- ; JSB WRITE ; Write to the terminal
- JMP DOLIN ; Good so do next line
-
-
- .SBTTL Finish up
- ;++
- ;Finish up
- ;--
- FINISH:
- ; Close the file(s)
- JSB CLTSK ; Close the task file if it isn't yet
- MOVAL RDFAB,R1 ; Get FAB for input file
- $CLOSE R1 ; Close the input file
- JSB RMSERR ; Check for file error
- END: MOVL #SS$_NORMAL,R0 ; Set up successful completion
- RET
-
- .SBTTL Close file
-
- ;++
- ; Close the output file if there is one open
- ;
- ; If there is an error the program stops with an RMS error
- ;
- ; Registers destroyed: R0, R1
- ; The OPENFL state is changed to file not open (OPENFL=0).
- ;--
-
- CLTSK: TSTL OPENFL ; See if the task file is open
- BEQL 10$ ; If not then just return
-
- ; Write last buffer if needed
- TSTL WTCOUNT ; See if there is any data not written
- BEQL 8$ ; If not then branch
- MOVAL WTRAB,R1 ; Get the RAB address
- $RAB_STORE RAB=R1,RSZ=WTCOUNT ; Put its size into the RAB.
- $WRITE R1 ; Put the buffer of data.
- JSB RMSERR ; Check for file error
-
- ; Close the file
- 8$: MOVAL WTFAB,R1 ; Get FAB for output file
- $CLOSE R1 ; Close output file
- JSB RMSERR ; Check for file error
- CLRL OPENFL ; Set the state to file not open
- 10$: RSB ; Return to sender
-
-
- .SBTTL Output and input to/from terminal
- ;++
- ; Write data to terminal.
- ; R10 Address of data to output
- ; R1 Length of data
- ;--
- WRITE:
- MOVW R1,MSGDSC ; Store the length in the descript blk
- MOVL R10,ADDR ; Store the address of the ASCII
- PUSHAQ MSGDSC ; Push the descriptor block address
- CALLS #1,G^LIB$PUT_OUTPUT ; Do the output
- RSB ; Return to sender
-
- ;++
- ; Read from the terminal
- ; R10 Address of buffer
- ; R1 Number of characters to read
- ; R11 Input prompt address
- ; R12 Length of prompt
- ;
- ;Returned:
- ; R0 Number of characters read
- ;--
- READ:
- MOVL R1,INP_STR_D ; Store the buffer length in desc block
- MOVL R10,INP_BUF ; Store the buffer address in desc blk
- MOVL R11,ADDR ; Store prompt address in desc block
- MOVW R12,MSGDSC ; Store length in desctriptor block
- PUSHAB INP_STR_LEN ; Address for string length
- PUSHAQ MSGDSC ; Push address of prompt descriptor blk
- PUSHAB INP_STR_D ; String buffer descriptor
- CALLS #3,G^LIB$GET_INPUT ; Get input string value
- MOVL INP_STR_LEN,R0 ; Get actual input length back
- RSB ; Return to sender
-
-
- .SBTTL RMS error routine
- ;++
- ;Check for RMS error
- ; Call with: R0 Status of last RMS call (automatically stored
- ; in R0 by RMS after an operation)
- ;
- ; Returned: R0 Status
- ; Registers destroyed: R0
- ; Program stops after error message is displayed if there is any type of error.
- ;--
- RMSERR:
- BLBC R0,60$ ; If error, go check it out
- MOVL #KNORMAL,R0 ; Set up a successful return code.
- RSB ; Return to caller
-
- ; Here if there is an RMS error we don't know how to handle
- 60$: PUSHL R0 ; Save the error code
- MOVAB M$RMS,R10 ; Get the address and length of the
- MOVL #L$RMS,R1 ; message to output
- JSB WRITE ; Output it
- POPL R0 ; Get the error code back
- RET ; Exit program
-
-
- .SBTTL Open the output file
- ;++
- ; Create and open the output file and set the file open flag
- ;
- ; Registers destroyed: R0, R1
- ; Program stops after error message is displayed if there is any type of error.
- ;--
-
- OPEN: MOVL #TRUE,OPENFL ; State that the file is open
- MOVAL WTFAB,R1 ; Put address of FAB into R1.
- $FAB_STORE FAB=R1,FAC=<BIO,GET> ; Set the block I/O in FAB.
- ;$FAB_STORE FAB=R1,FOP=CTG ; Tell RMS to make the task contiguous
- $CREATE #WTFAB ; Create the file
- JSB RMSERR ; Check for file error
- MOVAL WTRAB,R1 ; Put address of RAB into R1.
- ; Put address of user buffer and record buffer and sizes into RAB
- $RAB_STORE RAB=R1,UBF=WTBUF,RBF=WTBUF,USZ=#512.,RSZ=#512.
- $CONNECT #WTRAB ; Connect to record.
- JSB RMSERR ; Check for file error
- RSB ; Return to sender
-
- .SBTTL Put a character to the file
- ;++
- ; Put a character to the output file.
- ; The buffer is only written when 512. characters have been sent to the routine
- ; If the file does not end on a boundary then the buffer will have to be
- ; written by some other routine.
- ;
- ; Call with: R10 Contains the character to be put into file
- ; Registers destroyed: R1, R10
- ;
- ; Program stops after error message is displayed if there is any type of error.
- ;--
-
- PUT: PUSHL R10 ; Save the character
- MOVL WTCOUNT,R10 ; Get the offset into the buffer
- MOVB (SP),WTBUF(R10) ; Put the character
- TSTL (SP)+ ; Restore the stack
- INCL WTCOUNT ; Increment the offset into the buffer
- CMPL WTCOUNT,#512. ; Check to see if we are past the end
- BNEQ 10$ ; If not then branch
- MOVAL WTRAB,R1 ; Get the RAB address
- $RAB_STORE RAB=R1,RSZ=WTCOUNT ; Put its size into the RAB.
- $WRITE R1 ; Put the buffer of data.
- JSB RMSERR ; Check for file error
- CLRL WTCOUNT ; Clear the pointer
- 10$: RSB ; Return to sender
-
- .SBTTL Convert to binary
- ;++
- ; Convert 2 hexidecimal digits to binary
- ; Input is from the input buffer pointed to by R4 (it is incremented twice)
- ;
- ; Call with: R4 The pointer into the input buffer
- ; Returned: R10 The binary walue
- ; Registers destroyed: R10,R1
- ;--
-
- CVTBIN:
- CLRL R10 ; Clear R10 for the BISB
- BISB (R4)+,R10 ; Get the next digit
- JSB BIN ; in place and convert to binary
- ASHL #4,R10,R10 ; Multiply the result by 16
- MOVL R10,R1 ; and save it
- CLRL R10 ; Clear R10
- BISB (R4)+,R10 ; Get the next digit
- JSB BIN ; Convert to binary
- BISL R1,R10 ; Set the correct bits for high order
- ADDL2 R10,CHKSUM ; Add the value to the checksum
- RSB ; Return to sender
-
- BIN: CMPL R10,#^A/9/ ; Check to see if above '9
- BLEQ 1$ ; If not then branch
- SUBL2 #HEXOFFSET,R10 ; Subtract offset to alphabet
- 1$: SUBL2 #48.,R10 ; Make binary
- RSB ; Return to sender
-
-
- .SBTTL Receive a line of data
-
- ;++
- ; This will get a line of data from the input device
- ;
- ; Returned: R4 Address of start of data buffer
- ; Registers destroyed: R0, R1, R3, R4
- ;
- ; A checksum error will cause a NAK to be sent and input to be read again
- ; A real error will cause an error message to be output and the program to stop
- ;--
-
- RECEIVE:
- ; Here to read from a file
- MOVAL RDRAB,R1 ; Get the RAB address
- $GET R1 ; Get the record
- JSB RMSERR ; Check for file error
- MOVZWL #MAX.MSG,R3 ; Assume we got a full buffer
- ; Here to check the data we got
- RECCHK: MOVAL RDBUF,R4 ; Get the address of the information
- CLRL R1 ; Clear the data start address
- 80$: BICB #MSB,(R4) ; Clear parity bit
- SUBB3 #RCV.SOH,(R4)+,R0 ; Check for start of header
- BLSS 81$ ; If not, just keep going
- CMPB R0,#2 ; There are 3 possible headers
- BGTR 81$ ; Not a header
- MOVZBL R0,LNGADR ; Amount of extra bytes in the address
- MOVL R4,R1 ; Start of header so save it
- 81$: SOBGTR R3,80$ ; Repeat until done
- TSTL R1 ; Check to see if we got a SOH
- BNEQ 85$ ; If good then skip the jump
- JMP RECEIVE ; If not then re-read
- 85$: MOVL R1,R4 ; Move to R4 for use
- PUSHL R4 ; Save SOH pointer on stack
-
- JSB CVTBIN ; Convert all to binary to see if
- ; checksum is correct
- MOVL R10,R3 ; Get the length of data
- ADDL2 #4,R3 ; Add the length of address and field
- ; type and checksum
- ADDL2 LNGADR,R3 ; If long address, skip more bytes
- BLSS 94$ ; If we have a negative number then
- ; must have been a bad length
- CMPL R3,#MAX.MSG/2-1 ; If we got some length that is out of
- BGEQ 94$ ; range then NAK right away
- 92$: JSB CVTBIN ; Convert all to binary to see if
- SOBGTR R3,92$ ; the checksum is OK
- 93$: BICL #LEFTBYTE,CHKSUM ; We only want an 8 bit checksum
- TSTL CHKSUM ; Test for a zero checksum
- BEQL 95$ ; If OK then exit normally
- 94$: CLRL CHKSUM ; Clear the checksum for the line
- MOVAL M$NAK,R10 ; Get the address of the message
- MOVZBL #L$NAK,R1 ; Only write the first character to
- JSB WRITE ; the terminal
- TSTL (SP)+ ; Pull the pointer off the stack
- JMP RECEIVE ; Try to get the line again
-
- ; Return to sender
- 95$: POPL R4 ; Get the pointer back
- RSB ; Return to sender
-
-
- .SBTTL End of the Dehexify
-
- .END DEHEX
-